package com.hkedou.yuanhuo.shiro;

import org.apache.shiro.authc.Account;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.DefaultSubjectFactory;
import org.apache.shiro.mgt.SecurityManager;
import com.hkedou.yuanhuo.shiro.realm.ShiroRealm;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.mgt.DefaultWebSubjectFactory;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 权限配置加载
 *
 * @author ruoyi
 */
@Configuration
public class ShiroConfig {

    final static String DEBUG_PREFIX="-----------------------";

    private static Logger logger= LoggerFactory.getLogger("com.hkedou.shiro");


    //将自己的验证方式加入容器
    @Bean
    public ShiroRealm myShiroRealm() {
        ShiroRealm myShiroRealm = new ShiroRealm();
        return myShiroRealm;
    }

    //权限管理，配置主要是Realm的管理认证
    @Bean
    public SecurityManager securityManager( SessionManager sessionManager) {
        System.out.println("--------securityManager");
        DefaultWebSecurityManager securityManager = new TokenDefaultWebSecurityManager();
        securityManager.setSessionManager(sessionManager);
        securityManager.setSubjectFactory(subjectFactory());
//        securityManager.setCacheManager(cacheManager);
        securityManager.setRealm(myShiroRealm());

        /*
         * 禁用使用Sessions 作为存储策略的实现，但它没有完全地禁用Sessions
         * 所以需要配合context.setSessionCreationEnabled(false);
         */
        ((DefaultSessionStorageEvaluator)((DefaultSubjectDAO)securityManager.getSubjectDAO()).getSessionStorageEvaluator()).setSessionStorageEnabled(false);


        return securityManager;
    }


    @Bean

    public DefaultWebSubjectFactory subjectFactory(){
        DefaultWebSubjectFactory subjectFactory = new TokenDefaultSubjectFactory();
        return subjectFactory;

    }



    //Filter工厂，设置对应的过滤条件和跳转条件
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        System.out.println("--------shiroFilterFactoryBean");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        AccessControlFilter accessControlFilter =  new MyFormAuthenticationFilter();
//        return new TokenAccessControlFilter();
        shiroFilterFactoryBean.getFilters().put("token", accessControlFilter);
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        Map<String,String> map = new LinkedHashMap<>();
        //登出
        map.put("/logout","logout");
        map.put("/login", "anon");//对所有用户认证
        map.put("/test", "anon");//对所有用户认证
//        map.put("/**","authc");
        map.put("/**","token");
        //登录
        shiroFilterFactoryBean.setLoginUrl("/nologintips");
        accessControlFilter.setLoginUrl("/nologintips");
        accessControlFilter.processPathConfig("/hello","anon");

        //首页
        shiroFilterFactoryBean.setSuccessUrl("/");
        //错误页面，认证不通过跳转
        shiroFilterFactoryBean.setUnauthorizedUrl("/errortips");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
//        logger.error(DEBUG_PREFIX,new Exception("as"));

        return shiroFilterFactoryBean;
    }

    /**
     *  容器把自定义的CustomFormAuthenticationFilter也作为容器的filter接管,
     *  所有的请求又都经过一次filter,
     *  那么就会导致一个问题出现：
     *  比如：我们定义 /js/**=anon,/css/**=anon, /img/ =anno,
     *  那么所有JS/CSS/IMG等资源文件也会被拦截。
     *  http://412887952-qq-com.iteye.com/blog/2392741
     */
//    @Bean
//    public AccessControlFilter statelessAuthcFilter() {
//          return new MyFormAuthenticationFilter();
////        return new TokenAccessControlFilter();
//    }

    //加入注解的使用，不加入这个注解不生效
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        System.out.println("--------authorizationAttributeSourceAdvisor");
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

//    @Bean
//    public CacheManager cacheManager(){
//        RedisCacheManager redisCacheManager = new RedisCacheManager();
//        redisCacheManager.setRedisManager(redisManager());
//        return redisCacheManager;
//    }


    @Bean
    public SessionDAO sessionDAO(){
        System.out.println("-------- sessionDAO");
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setRedisManager(redisManager());
        return redisSessionDAO;
    }


    /**
     * 配置shiro redisManager
     * 使用的是shiro-redis开源插件
     *
     * @return
     */
    public RedisManager redisManager() {
        RedisManager redisManager = new RedisManager();
        redisManager.setHost("localhost");
        redisManager.setPort(6379);
//        redisManager.setExpire(1800);// 配置缓存过期时间
        redisManager.setTimeout(0);
//        redisManager.setPassword("665544");
        redisManager.setDatabase(2);
        // redisManager.setPassword(password);
        return redisManager;
    }

    @Bean
    public SimpleCookie simpleCookie(){
        SimpleCookie simpleCookie = new SimpleCookie("shiro.session");
        simpleCookie.setPath("/");
        return simpleCookie;
    }

    @Bean
    public SessionManager sessionManager(SessionDAO sessionDAO){
        System.out.println("--------sessionManager");
        DefaultWebSessionManager manager = new DefaultWebSessionManager();
        manager.setSessionDAO(sessionDAO);
        manager.setSessionIdCookie(simpleCookie());
        manager.setSessionValidationSchedulerEnabled(false);
//        manager.setGlobalSessionTimeout(360);
//        manager.setSessionValidationInterval(3600000);
        return manager;
    }
}
